//Copyright  2015 Max "Shrinker" Wieden
//Refer to license for license details.

Tokens:
	KeyCombo =
		['a'] //alt     //only in normal mode of operation
		['c'] //control //~
		['s'] //shift   //~
		(
			"Arrow" ("Down" | "Left" | "Right" | "Up")
		|	"Backspace"
		|	"Comma"
		|	"Delete"
		|	"End"
		|	"Escape"
		|	"Home"
		|	"Insert"
		|	"Minus"
		|	"Mouse" ((("Backward" | "Forward") "Button") | "Left" | "Middle" | "Right" | "Wheel" ("Down" | "Up"))
		|	"Num" (['0'-'9'] | "Asterisk" | "Minus" | "Plus" | "Slash")
		|	"Page" ("Down" | "Up")
		|	"Period"
		|	"Plus"
		|	"Return"
		|	"Space"
		|	"Tab"
		|	"Alt"   //only in basic pass-through mode of operation
		|	"Ctrl"  //~
		|	"Shift" //~
		|	'F' ("10" | "11" | "12" | ['1'-'9'])
		|	['A'-'Z']
		);
	KeyComboNumericPrefixed = //not an allowed QName part, but also allowed as a numeric literal
		(
			( 'a'  ['c'] ['s'])
		|	(       'c'  ['s'])
		|	(             's' )
		) ['0'-'9'];
	NumericLiteral = ['1'-'9'] (['0'-'9'])+; //['0'-'9'] matched with KeyComboNumericBare
	KeyComboNumericBare = ['0'-'9'];
	Colon     = ':';
	Comma     = ',';
	Minus     = '-';
	Period    = '.';
	Semicolon = ';';
	#FirstNameChar = ['A'-'Z'] | ['a'-'z'] | '_';
	Name = FirstNameChar (FirstNameChar | ['0'-'9'])*;

FillerTokens:
	SingleLineComment = "//" (~['\r', '\n'])* ["\r\n" | ['\r', '\n']];
	MultiLineComment  = "/*" (~['*'])* ('*')+ (~['*', '/'] (~['*'])* ('*')+)* '/';
	Whitespace        = (['\t', ' ', '\r', '\n'])+;

TokenSpecializations:

Rules:
Start = {
	(BindSequence | UnbindSequence)*
	EOF
}

BindSequence = {
	//this binds a sequence of key combinations to a command
	//already existing bindings are overwritten
	//a binding with an unknown command is treated as an UnbindSequence statement
	#AnyKeyCombo (Comma #AnyKeyCombo)* Colon (QName | #AnyNumericLiteral) Semicolon
}

UnbindSequence = {
	//this erases a binding of sequence of key combinations to trigger a command
	//this statement is ignored if the sequence is only the prefix of a currently active sequence
	Minus #AnyKeyCombo (Comma #AnyKeyCombo)* Semicolon
}

#AnyKeyCombo = {
	KeyCombo | KeyComboNumericPrefixed | KeyComboNumericBare
}

#AnyNumericLiteral = {
	NumericLiteral | KeyComboNumericBare
}

QName = {
	AnyName (AnyName | #AnyNumericLiteral)* (Period AnyName (AnyName | #AnyNumericLiteral)*)*
}

AnyName = {
	//concatenated into a single name, removing all FillerTokens
	(Name | KeyCombo | KeyComboNumericPrefixed) (Name | KeyCombo | KeyComboNumericPrefixed | NumericLiteral)*
}
